package com.atguigu.gmall.order.service.impl;

import com.atguigu.gmall.common.config.interceptor.UserAuthContext;
import com.atguigu.gmall.common.constant.RabbitConstant;
import com.atguigu.gmall.common.constant.RedisConstant;
import com.atguigu.gmall.common.execption.GmallException;
import com.atguigu.gmall.common.result.ResultCodeEnum;
import com.atguigu.gmall.common.util.JSONs;
import com.atguigu.gmall.common.util.MathUtil;
import com.atguigu.gmall.feign.cart.CartFeginClient;
import com.atguigu.gmall.feign.product.SkuInfoFeginClient;
import com.atguigu.gmall.feign.user.UserFeignClient;
import com.atguigu.gmall.feign.ware.WareFeignClient;
import com.atguigu.gmall.model.cart.entity.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.mq.to.order.OrderCreateTO;
import com.atguigu.gmall.model.mq.to.ware.WareDeductMsg;
import com.atguigu.gmall.model.mq.to.ware.WareStockMsg;
import com.atguigu.gmall.model.mq.to.ware.WareStockMsg.Detail;
import com.atguigu.gmall.model.order.entity.OrderDetail;
import com.atguigu.gmall.model.order.entity.OrderInfo;
import com.atguigu.gmall.model.order.entity.OrderStatusLog;
import com.atguigu.gmall.model.order.entity.PaymentInfo;
import com.atguigu.gmall.model.order.vo.OrderConfirmVo;
import com.atguigu.gmall.model.order.vo.OrderSplitParamVO;
import com.atguigu.gmall.model.order.vo.OrderSplitParamVO.WareSkuMap;
import com.atguigu.gmall.model.order.vo.OrderSplitResultVO;
import com.atguigu.gmall.model.order.vo.OrderSplitResultVO.DetailsDTO;
import com.atguigu.gmall.model.order.vo.OrderSubmitVo;
import com.atguigu.gmall.model.user.entity.UserAddress;
import com.atguigu.gmall.mq.service.RabbitService;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderDetailService;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.order.service.OrderStatusLogService;
import com.atguigu.gmall.order.service.PaymentInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * @author jiamin
 * @description 针对表【order_info(订单表 订单表)】的数据库操作Service实现
 * @createDate 2023-09-03 14:02:14
 */
@Service
@Slf4j
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo>
        implements OrderInfoService {

    @Autowired
    CartFeginClient cartFeginClient;

    @Autowired
    ThreadPoolExecutor executor;

    @Autowired
    SkuInfoFeginClient skuInfoFeginClient;

    @Autowired
    WareFeignClient wareFeignClient;

    @Autowired
    UserFeignClient userFeignClient;

    @Autowired
    UserAuthContext userAuthContext;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    OrderDetailService orderDetailService;

    @Autowired
    OrderStatusLogService orderStatusLogService;

    @Autowired
    RabbitService rabbitService;

    @Autowired
    PaymentInfoService paymentInfoService;


    @Transactional
    @Override
    public OrderConfirmVo getOrderConfirmVo() {
        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();

        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();


        CompletableFuture<List<OrderConfirmVo.Detail>> detailFuture = CompletableFuture.supplyAsync(() -> {
            //将主线程的请求头的信息放到新线程
            RequestContextHolder.setRequestAttributes(requestAttributes);
            //1. 查询商品清单
            List<CartInfo> cartInfoList = cartFeginClient.checkedList().getData();
            //转换为Detail对象
            List<OrderConfirmVo.Detail> details = cartInfoList.stream()
                    .parallel() //开启并行流
                    .map(item -> {
                        OrderConfirmVo.Detail detail = new OrderConfirmVo.Detail();
                        detail.setSkuId(item.getSkuId());
                        detail.setImgUrl(item.getImgUrl());
                        detail.setSkuName(item.getSkuName());
                        //实时查价格
                        BigDecimal price = skuInfoFeginClient.getPrice(item.getSkuId()).getData();
                        detail.setOrderPrice(price);
                        detail.setSkuNum(item.getSkuNum());
                        //查库存
                        String hasStock = wareFeignClient.hasStock(item.getSkuId(), item.getSkuNum());
                        detail.setHasStock(Integer.parseInt(hasStock));
                        return detail;
                    }).collect(Collectors.toList());
            orderConfirmVo.setDetailArrayList(details);
            //清除线程请求头，防止OOM
            RequestContextHolder.resetRequestAttributes();
            return details;
        }, executor);

        // 2. 查询商品总量、金额

        //计算总数量
        CompletableFuture<Void> totalNumFuture = detailFuture.thenAcceptAsync(details -> {
            //先拿到上面返回的数据reduce计算
            Integer totalNum = details.stream()
                    .map(OrderConfirmVo.Detail::getSkuNum)
                    .reduce(0, (o1, o2) -> o1 + o2);
            orderConfirmVo.setTotalNum(totalNum);
        }, executor);

        //计算总金额
        CompletableFuture<Void> totalAmountFuture = detailFuture.thenAcceptAsync(details -> {
            //先拿到上面返回的数据reduce计算
            BigDecimal totalAmount = details.stream()
                    .map(item -> item.getOrderPrice().multiply(new BigDecimal(item.getSkuNum())))
                    .reduce(new BigDecimal("0"), BigDecimal::add); //聚合计算，两两相加
            orderConfirmVo.setTotalAmount(totalAmount);
        }, executor);
        //3. 用户地址列表
        CompletableFuture<Void> userAddressFuture = CompletableFuture.runAsync(() -> {
            //获取用户地址信息需要要用到请求头信息，设置进去
            RequestContextHolder.setRequestAttributes(requestAttributes);
            List<UserAddress> userAddressList = userFeignClient.getUserAddressList().getData();
            orderConfirmVo.setUserAddressList(userAddressList);
            //业务结束需要清除RequestContextHolder里面的map里面的信息，防止OOM
            RequestContextHolder.resetRequestAttributes();
        }, executor);
        //
        // 4. 交易号
        String tradeNo = "ATGUIGU_" + System.currentTimeMillis() + "_" + userAuthContext.getUserAuth().getUserId();
        //防重复提交，这里存一份到redis，10min内提交订单时，把他删掉，如果删除成功，可以继续操作，删除失败视为重复提交
        stringRedisTemplate.opsForValue().set(RedisConstant.REDIS_REPEAT_TRADENO + tradeNo, "1", 10, TimeUnit.MINUTES);
        orderConfirmVo.setTradeNo(tradeNo);
        //异步编排需要全部结束再返回
        CompletableFuture.allOf(totalNumFuture, totalAmountFuture, userAddressFuture).join();

        return orderConfirmVo;
    }

    @Override
    @Transactional
    public Long submitOrder(String tradeNo, OrderSubmitVo orderSubmitVo) {
        //1. 防重复提交校验
        //  请求提交来，先删除令牌，如果能删除成功，代表第一次发请求，服务器进行处理，
        //如果删除失败，代表之前有人来过，删除了数据
//        每个令牌过期时间10min
        Boolean delete = stringRedisTemplate.delete(RedisConstant.REDIS_REPEAT_TRADENO + tradeNo);
        if (!delete) {
            throw new GmallException(ResultCodeEnum.ORDER_REPEAT_COMMIT_ERROR);
        }

        //2. 商品库存校验
        List<String> skuNmaes = orderSubmitVo.getOrderDetailList()
                .stream().parallel()//开启并行流
                .filter(item -> {
                    BigDecimal price = skuInfoFeginClient.getPrice(item.getSkuId()).getData();
                    return !MathUtil.bigDecimalEquals(price, item.getOrderPrice());
                }).map(OrderSubmitVo.OrderDetailListDTO::getSkuName)
                .collect(Collectors.toList());
        //如果不为空，说明订单里面有商品价格发生变动
        if (skuNmaes != null && skuNmaes.size() > 0) {
            String skuNamesStr = JSONs.objecttoString(skuNmaes);
            ResultCodeEnum orderPriceChangeError = ResultCodeEnum.ORDER_PRICE_CHANGE_ERROR;
            throw new GmallException(orderPriceChangeError.getMessage().replace("{}", skuNamesStr), orderPriceChangeError.getCode());
        }

        // 3. 商品价格校验
        List<String> noWareSkuNames = orderSubmitVo.getOrderDetailList()
                .stream().parallel()//开启并行流
                .filter(item -> {
                    String hasStock = wareFeignClient.hasStock(item.getSkuId(), item.getSkuNum());
                    return "0".equalsIgnoreCase(hasStock);
                }).map(OrderSubmitVo.OrderDetailListDTO::getSkuName)
                .collect(Collectors.toList());
        //如果不为空，说明订单里面有商品库存不足
        if (noWareSkuNames != null && noWareSkuNames.size() > 0) {
            String noWareSkuNamesStr = JSONs.objecttoString(noWareSkuNames);
            ResultCodeEnum orderPriceChangeError = ResultCodeEnum.ORDER_NO_WARE_ERROR;
            throw new GmallException(orderPriceChangeError.getMessage().replace("{}", noWareSkuNamesStr), orderPriceChangeError.getCode());
        }


        //能走到这里来，说明，前端传过来的数据已经没问题了
        //获取用户id
        Long userId = userAuthContext.getUserAuth().getUserId();


        OrderInfo orderInfo = buildOrderInfo(tradeNo, orderSubmitVo);
        // 保存订单基本信息
        this.save(orderInfo);
        //拿到保存后的id
        Long orderId = orderInfo.getId();

        // 保存订单商品信息
        List<OrderDetail> orderDetailList = orderSubmitVo.getOrderDetailList()
                .stream()
                .map(item -> {
                    OrderDetail orderDetail = new OrderDetail();
                    orderDetail.setOrderId(orderId);
                    orderDetail.setSkuId(item.getSkuId());
                    orderDetail.setSkuName(item.getSkuName());
                    orderDetail.setImgUrl(item.getImgUrl());
                    orderDetail.setOrderPrice(item.getOrderPrice());
                    orderDetail.setSkuNum(item.getSkuNum());
                    orderDetail.setCreateTime(new Date());
                    orderDetail.setSplitTotalAmount(item.getOrderPrice().multiply(new BigDecimal(item.getSkuNum())));
                    orderDetail.setSplitActivityAmount(new BigDecimal("0"));
                    orderDetail.setSplitCouponAmount(new BigDecimal("0"));
                    orderDetail.setUserId(userId);
                    return orderDetail;
                }).collect(Collectors.toList());

        orderDetailService.saveBatch(orderDetailList);

        //订单提交成功记录日志
        OrderStatusLog orderStatusLog = new OrderStatusLog();
        orderStatusLog.setOrderId(orderInfo.getId());
        orderStatusLog.setOrderStatus(orderInfo.getOrderStatus());
        orderStatusLog.setOperateTime(new Date());
        orderStatusLog.setUserId(userId);
        orderStatusLogService.save(orderStatusLog);

        //mq提交发送一个关单的消息
        OrderCreateTO msg = new OrderCreateTO();
        msg.setOrderId(orderId);
        msg.setUserId(userId);
        msg.setSendTime(new Date());
        msg.setType(RabbitConstant.RK_ORDER_CREATE);

        //30分钟后会提交到死信队列，消费者监听死信队列，就可以去判断消费执行关单逻辑
        rabbitService.sendMsg(RabbitConstant.EXCHANGE_ORDER_EVENT, RabbitConstant.RK_ORDER_CREATE, msg);
        return orderId;
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        Long userId = userAuthContext.getUserAuth().getUserId();
        OrderInfo one = lambdaQuery().eq(OrderInfo::getId, orderId)
                .eq(OrderInfo::getUserId, userId)
                .one();
        return one;

    }

    @Override
    public void cancelOrder(Long orderId, Long userId) {
        //要保证幂等性消息可能会被重复派送，业务执行就需要自己保证幂等，重复消息来了，就算执行了业务逻辑，数据库最终也是正确的业务状态
        //修改订单状态
        boolean update = lambdaUpdate().set(OrderInfo::getOrderStatus, OrderStatus.CLOSED.name())
                .set(OrderInfo::getProcessStatus, OrderStatus.CLOSED.name())
                .eq(OrderInfo::getUserId, userId)
                .eq(OrderInfo::getId, orderId)
                .eq(OrderInfo::getOrderStatus, OrderStatus.UNPAID.name()).update();
        if (update) {
            //修改成功，记录日志
            OrderStatusLog orderStatusLog = new OrderStatusLog();
            orderStatusLog.setOrderId(orderId);
            orderStatusLog.setOrderStatus(OrderStatus.CLOSED.name());
            orderStatusLog.setOperateTime(new Date());
            orderStatusLog.setUserId(userId);
            orderStatusLogService.save(orderStatusLog);
        } else {
            log.info("修改失败，已经被改变状态了");
        }
    }

    @Override
    @Transactional
    public void updateOrderStatusPayed(Map<String, String> params) {
        //先根据out_trade查询订单
        String[] split = params.get("out_trade_no").split("_");
        long userId = Long.parseLong(split[split.length - 1]);
        OrderInfo orderInfo = lambdaQuery().eq(OrderInfo::getOutTradeNo, params.get("out_trade_no"))
                .eq(OrderInfo::getUserId, userId)
                .one();
        //保证幂等性，利用CAS算法
        boolean update = lambdaUpdate().set(OrderInfo::getOrderStatus, OrderStatus.PAID.name())
                .set(OrderInfo::getProcessStatus, ProcessStatus.PAID.name())
                .eq(OrderInfo::getId, orderInfo.getId())
                .eq(OrderInfo::getUserId, userId)
                .in(OrderInfo::getOrderStatus, OrderStatus.UNPAID.name(), OrderStatus.CLOSED.name())
                .update();
        if (update) {
            //成功 记录日志
            OrderStatusLog orderStatusLog = new OrderStatusLog();
            orderStatusLog.setOrderId(orderInfo.getId());
            orderStatusLog.setOrderStatus(orderInfo.getOrderStatus());
            orderStatusLog.setOperateTime(new Date());
            orderStatusLog.setUserId(userId);
            orderStatusLogService.save(orderStatusLog);

            // 记录支付下信息
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
            paymentInfo.setOrderId(orderInfo.getId());
            //支付类型（微信 支付宝）
            paymentInfo.setPaymentType(params.get("payment_way"));
            //交易编号
            paymentInfo.setTradeNo(params.get("trade_no"));
            paymentInfo.setTotalAmount(orderInfo.getTotalAmount());
            paymentInfo.setSubject(params.get("subject"));
            paymentInfo.setPaymentStatus(params.get("trade_status"));
            paymentInfo.setCreateTime(new Date());
            paymentInfo.setCallbackTime(new Date());
            paymentInfo.setCallbackContent(JSONs.objecttoString(params));
            paymentInfo.setUserId(userId);
            paymentInfoService.save(paymentInfo);


            //发消息去通知库存系统减库存
            WareStockMsg msg = getWareStockMsg(userId, orderInfo);
            rabbitService.sendMsg(RabbitConstant.EXCHANGE_WARE_STOCK, RabbitConstant.RK_ORDER_WARE_STOCK, msg);


        }


    }

    @Override
    public void updateOrderStock(WareDeductMsg msg) {
        //判断是否扣减成功
        //    private Long orderId;
        //    private String status;
        //    // 状态： ‘DEDUCTED’  (已减库存)
        //    // 状态：  ‘OUT_OF_STOCK’  (库存超卖)
        OrderInfo orderInfo = getById(msg.getOrderId());
        OrderStatus os = OrderStatus.WAITING_DELEVER;
        ProcessStatus ps = ProcessStatus.WAITING_DELEVER;
        switch (msg.getStatus()) {
            case "DEDUCTED":
                os = OrderStatus.WAITING_DELEVER;
                ps = ProcessStatus.NOTIFIED_WARE;
                break;
            case "OUT_OF_STOCK":
                os = OrderStatus.WAITING_SCHEDULE;
                ps = ProcessStatus.STOCK_EXCEPTION;
                break;
        }
        //保证幂等性
        boolean update = lambdaUpdate()
                .set(OrderInfo::getOrderStatus, os)
                .set(OrderInfo::getProcessStatus, ps)
                .eq(OrderInfo::getId, orderInfo.getId())
                .eq(OrderInfo::getUserId, orderInfo.getUserId())
                .eq(OrderInfo::getOrderStatus, OrderStatus.PAID.name())
                .update();
        if (update) {
            //如果修改成功，记录日志
            OrderStatusLog orderStatusLog = new OrderStatusLog();
            orderStatusLog.setOrderId(orderInfo.getId());
            orderStatusLog.setOrderStatus(os.name());
            orderStatusLog.setOperateTime(new Date());
            orderStatusLog.setUserId(orderInfo.getUserId());
            orderStatusLogService.save(orderStatusLog);


        }
        //TODO 3、库存预警消息发送【发短信、发邮件、对接供货商】; 提示商品需要调货部署
        if (msg.getStatus().equals("OUT_OF_STOCK")) {
            //1、查询订单购买了哪些商品，几件。
            log.info("库存超卖，正在通知供货商进行补货...");
        }

    }

    @Override
    public List<OrderSplitResultVO> orderSplit(OrderSplitParamVO paramVO) {
        //先拿到数据
        String wareSkuMapStr = paramVO.getWareSkuMap();
        Long orderId = paramVO.getOrderId();
        //先拿到订单数据和顶单详情数据
        OrderInfo parentOrderInfo = getById(orderId);


        //保证幂等性，订单已经拆单就无需再次拆单
        if (OrderStatus.SPLIT.name().equals(parentOrderInfo.getOrderStatus())) {
            throw new GmallException(ResultCodeEnum.ORDER_SPLIT_ERROR);
        }
        //如果订单已经拆分就不用查详情了
        List<OrderDetail> orderDetailList = orderDetailService.lambdaQuery()
                .eq(OrderDetail::getOrderId, orderId)
                .eq(OrderDetail::getUserId, parentOrderInfo.getUserId())
                .list();

        List<WareSkuMap> wareSkuMaps =
                JSONs.stringToObj(wareSkuMapStr, new TypeReference<List<WareSkuMap>>() {
                });

        //能走到这里就说明该订单需要拆单
        AtomicInteger index = new AtomicInteger(1);
        List<OrderSplitResultVO> resultVOList = wareSkuMaps.stream()
                .map(item -> {
                    //保存子单和子单的详情
                    OrderInfo orderInfo = saveChildOrderAndDetail(parentOrderInfo, orderDetailList, index, item);
                    //构建返回值
                    OrderSplitResultVO resultVO = new OrderSplitResultVO();
                    resultVO.setOrderBody(orderInfo.getTradeBody());
                    resultVO.setConsignee(orderInfo.getConsignee());
                    resultVO.setOrderComment(orderInfo.getOrderComment());
                    resultVO.setWareId(item.getWareId());
                    resultVO.setOrderId(orderInfo.getId());
                    resultVO.setDeliveryAddress(orderInfo.getDeliveryAddress());
                    List<DetailsDTO> collect = orderInfo.getOrderDetailList().stream()
                            .map(orderDetail -> {
                                DetailsDTO detailsDTO = new DetailsDTO();
                                detailsDTO.setSkuName(orderDetail.getSkuName());
                                detailsDTO.setSkuId(orderDetail.getSkuId());
                                detailsDTO.setSkuNum(orderDetail.getSkuNum());
                                return detailsDTO;

                            }).collect(Collectors.toList());
                    resultVO.setDetails(collect);
                    resultVO.setPaymentWay(orderInfo.getPaymentWay());
                    return resultVO;
                }).collect(Collectors.toList());
        //子单保存成功以后，修改父单的状态
        boolean update = lambdaUpdate()
                .set(OrderInfo::getOrderStatus, OrderStatus.SPLIT.name())
                .set(OrderInfo::getProcessStatus, ProcessStatus.SPLIT.name())
                .eq(OrderInfo::getId, orderId)
                .eq(OrderInfo::getUserId, parentOrderInfo.getUserId())
                //保证幂等性，只有已经支付的订单才会修改
                .eq(OrderInfo::getOrderStatus, OrderStatus.PAID.name())
                .update();
        if (update) {
            //修改成功，记录订单状态日志
            OrderStatusLog orderStatusLog = new OrderStatusLog();
            orderStatusLog.setOrderId(orderId);
            orderStatusLog.setOrderStatus(OrderStatus.SPLIT.name());
            orderStatusLog.setOperateTime(new Date());
            orderStatusLog.setUserId(parentOrderInfo.getUserId());
            orderStatusLogService.save(orderStatusLog);
        }
        return resultVOList;
    }

    private OrderInfo saveChildOrderAndDetail(OrderInfo parentOrderInfo, List<OrderDetail> orderDetailList, AtomicInteger index, WareSkuMap item) {
        //先拆分为子单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setConsignee(parentOrderInfo.getConsignee());
        orderInfo.setConsigneeTel(parentOrderInfo.getConsigneeTel());
        //拿到子单列表，后面需要用
        List<OrderDetail> childDetail = orderDetailList.stream()
                .filter(orderDetail -> item.getSkuIds().contains(orderDetail.getSkuId())).collect(Collectors.toList());
        //计算子单价格
        BigDecimal totlePrice = childDetail.stream()
                .map(orderDetail -> orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum())))
                .reduce(new BigDecimal(0), BigDecimal::add);
        orderInfo.setTotalAmount(totlePrice);
        orderInfo.setOrderStatus(parentOrderInfo.getOrderStatus());
        orderInfo.setUserId(parentOrderInfo.getUserId());
        orderInfo.setPaymentWay(parentOrderInfo.getPaymentWay());
        orderInfo.setDeliveryAddress(parentOrderInfo.getDeliveryAddress());
        orderInfo.setOrderComment(parentOrderInfo.getOrderComment());
        orderInfo.setOutTradeNo("chirld" + index.getAndIncrement() + ":" + parentOrderInfo.getOutTradeNo());
        orderInfo.setTradeBody(parentOrderInfo.getTradeBody());
        orderInfo.setCreateTime(new Date());
        orderInfo.setExpireTime(parentOrderInfo.getExpireTime());
        orderInfo.setProcessStatus(orderInfo.getProcessStatus());
        orderInfo.setTrackingNo(parentOrderInfo.getTrackingNo());
        orderInfo.setParentOrderId(parentOrderInfo.getId());
        orderInfo.setImgUrl(childDetail.get(0).getImgUrl());
        orderInfo.setProvinceId(parentOrderInfo.getProvinceId());
        orderInfo.setOperateTime(new Date());
        orderInfo.setActivityReduceAmount(new BigDecimal(0));
        orderInfo.setCouponAmount(new BigDecimal(0));
        orderInfo.setOriginalTotalAmount(parentOrderInfo.getOriginalTotalAmount());
        orderInfo.setFeightFee(new BigDecimal(0));
        orderInfo.setRefundableTime(parentOrderInfo.getRefundableTime());

        this.save(orderInfo);
        childDetail.stream()
                .forEach(orderDetail -> {
                    orderDetail.setId(null);
                    orderDetail.setOrderId(orderInfo.getId());
                    orderDetail.setCreateTime(new Date());
                });
        orderInfo.setOrderDetailList(childDetail);
        //保存订单详情
        orderDetailService.saveBatch(childDetail);
        return orderInfo;
    }

    @NotNull
    private WareStockMsg getWareStockMsg(long userId, OrderInfo orderInfo) {
        WareStockMsg msg = new WareStockMsg();
        msg.setOrderId(orderInfo.getId());
        msg.setConsignee(orderInfo.getConsignee());
        msg.setConsigneeTel(orderInfo.getConsigneeTel());
        msg.setOrderComment(orderInfo.getOrderComment());
        msg.setOrderBody(orderInfo.getTradeBody());
        msg.setDeliveryAddress(orderInfo.getDeliveryAddress());
        msg.setPaymentWay(orderInfo.getPaymentWay());
        List<OrderDetail> list = orderDetailService.lambdaQuery()
                .eq(OrderDetail::getOrderId, orderInfo.getId())
                .eq(OrderDetail::getUserId, userId)
                .list();
        List<Detail> collect = list.stream()
                .map(item -> {
                    Detail detail = new Detail();
                    detail.setSkuId(item.getSkuId());
                    detail.setSkuNum(item.getSkuNum());
                    detail.setSkuName(item.getSkuName());
                    return detail;
                }).collect(Collectors.toList());
        msg.setDetails(collect);
        return msg;
    }

    private OrderInfo buildOrderInfo(String tradeNo, OrderSubmitVo orderSubmitVo) {
        OrderInfo orderInfo = new OrderInfo();
        //收货人
        orderInfo.setConsignee(orderSubmitVo.getConsignee());
        //收件人电话
        orderInfo.setConsigneeTel(orderSubmitVo.getConsigneeTel());
        //计算总金额
        BigDecimal totalAmount = orderSubmitVo.getOrderDetailList()
                .stream()
                .map(item -> item.getOrderPrice().multiply(new BigDecimal(item.getSkuNum())))
                .reduce(new BigDecimal("0"), BigDecimal::add);
        orderInfo.setTotalAmount(totalAmount);

        //订单状态
        String name = OrderStatus.UNPAID.name();
        orderInfo.setOrderStatus(name);
        //用户Id
        orderInfo.setUserId(userAuthContext.getUserAuth().getUserId());
        //付款方式
        orderInfo.setPaymentWay("1");
        //送货地址
        orderInfo.setDeliveryAddress(orderSubmitVo.getDeliveryAddress());
        //订单备注
        orderInfo.setOrderComment(orderSubmitVo.getOrderComment());
        //订单交易编号（第三方支付用)
        orderInfo.setOutTradeNo(tradeNo);
        //订单描述(第三方支付用),后面补充
//        orderInfo.setTradeBody();
        //创建时间
        orderInfo.setCreateTime(new Date());
        //失效时间 当前时间戳加上30分钟的时间戳
        long times = System.currentTimeMillis() + 1000 * 60 * 30;
        orderInfo.setExpireTime(new Date(times));
        String proName = ProcessStatus.UNPAID.name();
        //进度状态 后台人员看的
        orderInfo.setProcessStatus(proName);
        //物流单编号 后面填写
//        orderInfo.setTrackingNo();
        //父订单编号 没有就是0
        orderInfo.setParentOrderId(0L);
        //图片路径 拿订单第一个商品图片为订单默认图片
        orderInfo.setImgUrl(orderSubmitVo.getOrderDetailList().get(0).getImgUrl());
        //省id 不管
//        orderInfo.setProvinceId();
        //最后操作时间
        orderInfo.setOperateTime(new Date());
        //先不管
        orderInfo.setActivityReduceAmount(new BigDecimal("0"));
        orderInfo.setCouponAmount(new BigDecimal("0"));
        //原价金额
        orderInfo.setOriginalTotalAmount(totalAmount);
        orderInfo.setFeightFee(new BigDecimal("0"));
        //可退款日期（签收后30天）
        long time = System.currentTimeMillis() + 1000 * 60 * 60 * 24 * 30;
        orderInfo.setRefundableTime(new Date(time));
        return orderInfo;
    }
}




